//
// Created by 王岩松 on 2020/3/31.
//

#ifndef FORMANT_PITCH_H
#define FORMANT_PITCH_H


#include <algorithm>
#include "sound.h"
#include "stft.h"

#define AC_HANNING  0

#define NUM_PEAK_INTERPOLATE_SINC70  3
#define NUM_PEAK_INTERPOLATE_SINC700  4

#define NUM_VALUE_INTERPOLATE_NEAREST  0
#define NUM_VALUE_INTERPOLATE_LINEAR  1
#define NUM_VALUE_INTERPOLATE_CUBIC  2


#define NUM_PEAK_INTERPOLATE_NONE  0
#define NUM_PEAK_INTERPOLATE_PARABOLIC  1
#define NUM_PEAK_INTERPOLATE_CUBIC  2
#define NUM_PEAK_INTERPOLATE_SINC70  3
#define NUM_PEAK_INTERPOLATE_SINC700  4

struct Pitch_frame{
    vector<double> frequnce, strength;
    int nCandidates;
    double intensity;
};
struct Pitch{
    vector<Pitch_frame> candidates;
    double physicalDuration;
    int nFrames;
    double dt;
    double t1;
    void Pitch_create(double _physicalDuration, int _nFrames, double _dt, double _t1);
    double Sampled_indexToX(int index);
    int Sampled_xToLowIndex(double time);
    int Pitch_getMaxnCandidates();
    double getPitchAtX(double time, bool interpolate);
    void Free();

    template <class T>
    static void freeVector(vector<T> &A){
        vector<T>().swap(A);
    }
    template <class T>
    static void freeVV(vector<vector<T>> &A){
        for(int i = 0; i < A.size(); ++ i) {
            freeVector(A[i]);
        }
        freeVector(A);
    }

};

Pitch Sound_to_Pitch (sound me, double timeStep, double minimumPitch, double maximumPitch);
Pitch Sound_to_Pitch_ac (sound me,
                         double dt, double minimumPitch, double periodsPerWindow, int maxnCandidates, int accurate,
                         double silenceThreshold, double voicingThreshold,
                         double octaveCost, double octaveJumpCost, double voicedUnvoicedCost, double ceiling);
Pitch Sound_to_Pitch_any (sound me,
                          double dt, double minimumPitch, double periodsPerWindow, int maxnCandidates,
                          int method,
                          double silenceThreshold, double voicingThreshold,
                          double octaveCost, double octaveJumpCost, double voicedUnvoicedCost, double ceiling);

#endif //FORMANT_PITCH_H
